"""
51. N 皇后
按照国际象棋的规则，皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例 1：
输入：n = 4
输出：[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释：如上图所示，4 皇后问题存在两个不同的解法。
"""
from typing import List


class Solution:

    def __init__(self):
        self.res = []

    def solveNQueens(self, n: int) -> List[List[str]]:
        # 选择
        board = [['.' for j in range(n)] for i in range(n)]
        self.backTrack(board, 0)
        return self.res

    def backTrack(self, board: List[List[str]], row: int):
        if row == len(board):
            self.res.append([''.join(board[i]) for i in range(len(board))])
            return

        n = len(board[row])
        for col in range(n):
            # 排除不合法的选择
            if not self.isValid(board, row, col):
                continue
            # 前置左选择
            board[row][col] = 'Q'
            self.backTrack(board, row + 1)
            # 后置撤销选择
            board[row][col] = '.'

    def isValid(self, board: List[List[str]], row, col):
        n = len(board)
        # 验证列是否有n皇后冲突
        for i in range(row):
            if board[i][col] == 'Q':
                return False

        # 验证右上是否有n皇后冲突
        for i, j in zip(range(row - 1, -1, -1), range(col + 1, n)):
            if board[i][j] == 'Q':
                return False

        # 验证左上是否有n皇后冲突
        for i, j in zip(range(row - 1, -1, -1), range(col - 1, -1, -1)):
            if board[i][j] == 'Q':
                return False

        return True


if __name__ == '__main__':
    n = 4
    row = 3
    col = 3
    print(zip(range(row - 1, -1, -1), range(col + 1, n)))
    sl = Solution()
    sl.solveNQueens(4)
    print(sl.res)
    print(len(sl.res))